﻿package at.geoathome.utils.lang
{
	import flash.events.EventDispatcher;
	import flash.events.Event;
	
	/**
	* @author Georg Kamptner
	* MultiLanguage is implemented as Singleton
	*/
	public class MultiLanguage extends EventDispatcher
	{
		private var _languages:Object;
		private var _default_language:String;
		
		private static var _instance:MultiLanguage;
		
		public static const GERMAN:String = "de";
		public static const ENGLISH:String = "en";
		
		public function MultiLanguage(singleton_enforcer:SingletonEnforcer) 
		{
			_languages = new Object();
			_default_language = null;
		}
		
		public static function getInstance():MultiLanguage
		{
		  if (_instance == null)
			_instance = new MultiLanguage(new SingletonEnforcer());
			
		  return _instance;
		}
		
		
		private function languageExists(language_code:String):Boolean
		{
			if (_languages[language_code] != undefined && _languages[language_code] != null && _languages[language_code] is Object)
				return true;
				
			return false;
		}
		
		private function _getTranslation(string_id:String, language_code:String = null):String
		{
			if (language_code == null)
				language_code = _default_language;
			
			if (getLanguage(language_code) == null)
				return string_id;
				
			// if _language[language_code][string_id] is not available, use _language[_default_language] instead
			if (getLanguage(language_code).getString(string_id) == string_id)
			{
				return getLanguage(_default_language).getString(string_id);
			}
			
			return getLanguage(language_code).getString(string_id);
		}
		
		private function getLanguage(language_code:String):Language
		{
			if (language_code == null)
				return null;
				
			if (!languageExists(language_code)) // return the required language if available
			{
				if (!languageExists(_default_language)) // return default langauge if available
					return null;
				else
					return _languages[_default_language];
			}
			
			return _languages[language_code];
		}
		
		// Attention: this method overrides old languages.
		private function addLanguage(language_code:String, xml_path:String):void {
			_languages[language_code] = new Language(language_code, xml_path);
		}
		
		// Adds the {instance, string ID} pair into the internal array for later use.
		private function _addDelayedInstance(instance:Object, string_id:String, language_code:String = null):void
		{
			if (language_code == null)
				language_code = _default_language;
			getLanguage(language_code).addReceiver(instance, string_id);
		}
		
		// Adds the {languageCode and languagePath} pair into the internal array for later use.
		private function _addXMLPath(language_code:String, xml_path:String):void
		{
			// update xml path only if language is available
			if (languageExists(language_code) && getLanguage(_default_language).loaded)
			{
				getLanguage(language_code).xml_path = xml_path;
				return;
			}
				
			// otherwise crete a new language
			addLanguage(language_code, xml_path);
		}
		
		// Returns true if the XML file is loaded; false otherwise.
		private function _checkXMLStatus():Boolean {
			return getLanguage(_default_language).loaded;
		}
		
		// The default language code as set in the Strings panel dialog box or by calling the setDefaultLang() method.
		private function _getDefaultLang():String {
			return _default_language;
		}
		
		// Loads the specified XML language file.
		private function _loadLanguageXML(language_code:String, custom_xml_complete_callback:Function = null):void {
			getLanguage(language_code).loadLanguageXML(null, false, custom_xml_complete_callback);
		}
		
		// Sets the default language code.
		private function _setDefaultLang(language_code:String):void {
			_default_language = language_code;
		}
		
		// Sets the new string value of a given string ID and language code.  Attention! It overrides existing values.
		private function _setString(string_id:String, language_code:String, string_value:String):void {
			getLanguage(language_code).setString(string_id, string_value);
		}
		
		public override function toString():String
		{
			var str:String = "";
			
			str += "\n [com.kronomy.utils.lang.MultiLanguage] \n ";
			for (var i:String in _languages)
			{
				str += "\n lang: " + i + " \n " + _languages[i].toString();
			}
			
			return str;
		}
		
		
		// - STATIC API ----------------------------------------------------------------------------
		public static function getTranslation(string_id:String, language_code:String = null):String {
			return MultiLanguage.getInstance()._getTranslation(string_id, language_code);
		}
		
		// [static] Adds the {instance, string ID} pair into the internal array for later use.
		public static function addDelayedInstance(instance:Object, string_id:String, language_code:String = null):void {
			MultiLanguage.getInstance()._addDelayedInstance(instance, string_id, language_code);
		}
		
		// [static] Adds the {languageCode and languagePath} pair into the internal array for later use.
		public static function addXMLPath(language_code:String, path:String):void {
			MultiLanguage.getInstance()._addXMLPath(language_code, path);
		}
		
		// [static] Returns true if the XML file is loaded; false otherwise.
		public static function checkXMLStatus():Boolean {
			return MultiLanguage.getInstance()._checkXMLStatus();
		}
		
		// [static] The default language code as set in the Strings panel dialog box or by calling the setDefaultLang() method.
		public static function getDefaultLang():String {
			return MultiLanguage.getInstance()._getDefaultLang();
		}
		
		// [static] Loads the specified XML language file.
		public static function loadLanguageXML(language_code:String, custom_xml_complete_callback:Function = null):void {
			MultiLanguage.getInstance()._loadLanguageXML(language_code, custom_xml_complete_callback);
		}
		
		// [static] Returns the string value associated with the given string ID in the default language.
		public static function loadString(string_id:String):String {
			return MultiLanguage.getInstance()._getTranslation(string_id);
		}
		
		// [static] Returns the string value associated with the given string ID and language code.
		public static function loadStringEx(string_id:String, language_code:String):String {
			return MultiLanguage.getInstance()._getTranslation(string_id, language_code);
		}
		
		// [static] Sets the default language code.
		public static function setDefaultLang(language_code:String):void {
			MultiLanguage.getInstance()._setDefaultLang(language_code);
		}
		
		// [static] Sets the new string value of a given string ID and language code. 
		public static function setString(string_id:String, language_code:String, string_value:String):void {
			MultiLanguage.getInstance()._setString(string_id, language_code, string_value);
		}
		
	}
	
}

class SingletonEnforcer {}